﻿using EversysApi.Services;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DuBaiCoffee2.Model
{
    public class NetSerialPort : ISerialPort
    {

        public event Action DataReceived = delegate { };

        private SerialPort port;

        public string[] GetPortNames()
        {
            return new string[1] { IPorPortInfo.Instance.CoffeePortName };//SerialPort.GetPortNames();
        }
        public ISerialPort Init(string portName, int baudRate)
        {
            Console.WriteLine(portName);
            if (port != null) port.Close();
            port = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
            DataReceived = null;
            return this;
        }

        public bool IsOpen
        {
            get => port != null ? port.IsOpen : false;
        }

        public void Open()
        {
            port.Open();
            port.DataReceived += delegate {
                DataReceived();
            };
        }

        public int BaudRate
        {
            get => port.BaudRate;
            set => port.BaudRate = value;
        }

        public string PortName
        {
            get => port.PortName;
            set => port.PortName = value;
        }

        public int ReadBufferSize
        {
            get => port.ReadBufferSize;
            set => port.ReadBufferSize = value;
        }

        public int Read(byte[] buffer, int offset, int count)
        {
            int nbrOfBytes = port.Read(buffer, offset, count);
#if LogRawData
            int packetEnd = Array.IndexOf( buffer, (byte)0 );

            if( packetEnd > 0 )
            {
                byte[] relevantBufferPart = new byte[packetEnd];
                Buffer.BlockCopy( buffer, offset, relevantBufferPart, 0, packetEnd );
                LogRawData( relevantBufferPart, Direction_t.In_e );
            }
#endif
            return nbrOfBytes;
        }

        public int WriteBufferSize
        {
            get => port.WriteBufferSize;
            set => port.WriteBufferSize = value;
        }

        public void Write(byte[] buffer, int offset, int count)
        {
            port.Write(buffer, offset, count);
#if LogRawData
            LogRawData(buffer,Direction_t.Out_e);
#endif
        }

        public void Close()
        {
            port.Close();
        }

#if LogRawData
        private enum WriteTo_t
        {
            Console_e,
            File_e,
        }

        private enum Direction_t
        {
            Out_e,
            In_e,
        }

        private bool LogRawData(byte[] buffer, Direction_t direction)
        {
            WriteTo_t logDest = WriteTo_t.Console_e;

            if (buffer != null)
            {
                string str = ( ( direction == Direction_t.Out_e ) ? "=> " : "<= " ) + DateTime.Now.ToString("o") + ": ";
                foreach (var b in buffer)
                {
                    str += "0x" + b.ToString("X2") + ", ";
                }

                if (logDest == WriteTo_t.File_e)
                {
                    Console.WriteLine(str);
                }
                else
                {
                    FileStream fs = null;
                    StreamWriter sw = null;

                    try
                    {
                        string fileName = "RawDataLog.txt";

                        fs = File.Open( fileName, FileMode.Append );

                        sw = new StreamWriter( fs, System.Text.Encoding.Unicode );

                        sw.WriteLine( str );
                    }
                    catch { }

                    try
                    {
                        if( sw != null )
                        {
                            sw.Close( );
                            sw.Dispose( );
                        }
                    }
                    catch { }

                    try
                    {
                        if( fs != null )
                        {
                            fs.Close( );
                            fs.Dispose( );
                        }
                    }
                    catch { }
                }
            }

            return true;
        }
#endif

    }
}
